package com.jsl;

import com.google.gson.Gson;
import org.apache.commons.lang3.StringUtils;

import java.io.*;
import java.lang.reflect.Type;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;

import com.jsl.utils21.*;
import weaver.file.Prop;

public class NCCloud21Service {


    // app_secret
    private static String client_secret = null;
    // 公钥
    private static String pubKey = null;
    // app_id
    private static String client_id = null;
    // ncc用户名
    private static String username = null;
    private static String usercode = null;
    // ncc用户名密码
    private static String pwd = null;
    // ncc账套
    private static String busi_center = null;
    private static String dsname = null;
    // 获取token方式：client_credentials、password
    private static String grant_type =  "client_credentials";
    // 服务器ip：port
    private static String baseUrl = null;
    // 返回值压缩加密级别
    private static String secret_level = null;
    // 请求参数
    private static String requestBody = null;
    // openapi请求路径
    private static String apiUrl = null;

    // 访问api获取到的access_token
    public static String token = null;
    // 重复调用检查
    public static String repeat_check = null;
    // 接口调用业务标识
    public static String busi_id = null;


    /**
     * 启动入口
     *
     * @param args
     */
    public static void main(String[] args) {
        String a = "4_1001M11000000000CJI6";
        System.out.println(a.substring(2));
//        try {
////			// 初始化数据
//            testInit();
////			// 请求token
//            if (token == null) {
//                token = getToken();
//            }
//            System.out.println("getTokenData:" + token);
//            // 测试openapi
//          //  testApi(token);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
    }

    private static void testInit() {
        client_secret = "9db162ae4ae54a4884bf";
        client_id = "hboa";
        pubKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm1seDj5VEcyD6IKZPhy6e4Hp6mDe4KYs5mUa58c2toDJuIJRsirIB7MYCiDiYNLx8yFm6AeTQ8FF9nS6D9yK+HfTEOxliY44LwjpQGtNM9Wzjfi0HTSWMA6eUqnuGxFa9K9TpPtd3d6b1YhAUegaU0U2Yhj8bVI0fhh4GGLsC+JrT8N2hreaE3EmBB6h+iCRYJICYq/rrCMPaoscX6iPvH/CphtEVwQHctVN5mKitQLm4xylSnMMdnrIBrEwR1jpDVPIlN8lzG3PVVMGcAXuE4BDnw8x2mbf4WQ9UJHzaLTPh4p8C0AhDITjwMOXaCRBcSLjj2MAbWUoB6uKJUe0kwIDAQAB";
        username = "hboa";
        pwd = "jsl123456";
        busi_center = "01";
        baseUrl = "http://172.16.68.147";
        grant_type = "client_credentials";
        secret_level = "L0";
    }
    /**
     * 初始化参数
     */
    private static void init() {
        client_secret = Prop.getPropValue("JslWorkflow", "nc21_client_secret");
        client_id = Prop.getPropValue("JslWorkflow", "nc21_client_id");
        pubKey = Prop.getPropValue("JslWorkflow", "nc21_pubKey");
        username = Prop.getPropValue("JslWorkflow", "nc21_username");
        pwd = Prop.getPropValue("JslWorkflow", "nc21_pwd");
        busi_center = Prop.getPropValue("JslWorkflow", "nc21_busi_center");
        baseUrl = Prop.getPropValue("JslWorkflow", "nc21_baseUrl");
        //requestBody = Prop.getPropValue("JslWorkflow", "nc21_requestBody");
        //apiUrl = Prop.getPropValue("JslWorkflow", "nc21_apiUrl");
        grant_type = Prop.getPropValue("JslWorkflow", "nc21_grant_type");
        secret_level = Prop.getPropValue("JslWorkflow", "nc21_secret_level");
        //repeat_check = Prop.getPropValue("JslWorkflow", "nc21_repeat_check");
        //busi_id = Prop.getPropValue("JslWorkflow", "nc21_busi_id");
    }


    /**
     * 请求openapi
     *
     * @param apiUrl 请求body参数加密压缩用的key
     * @throws Exception
     */
    public static String pushData(String apiUrl, String requestBody) throws Exception {
        init();
        String token = getToken();
        // token转对象，获取api访问所用token和secret
        ResultMessageUtil returnData = new Gson().fromJson(token, (Type) ResultMessageUtil.class);

        Map<String, String> data = (Map<String, String>) returnData.getData();
        String access_token = data.get("access_token");
        String security_key = data.get("security_key");
        String refresh_token = data.get("refresh_token");

        // 请求路径
        String url = baseUrl + apiUrl;
        // 构造header参数
        Map<String, String> headermap = new HashMap<>();
        headermap.put("access_token", access_token);
        headermap.put("client_id", client_id);
        // 请求体签名
        StringBuffer sb = new StringBuffer();
        sb.append(client_id);
        if (StringUtils.isNotBlank(requestBody)) {
            sb.append(requestBody);
        }
        sb.append(pubKey);
        // 将请求体签名（client_id+requestBody+pubKey）
        String sign = SHA256Util.getSHA256(sb.toString(),pubKey);

        headermap.put("signature", sign);

        if (StringUtils.isNotBlank(pubKey)) {
            headermap.put("busi_id",pubKey);
        }
//        if (StringUtils.isNotBlank(repeat_check)) {
//            headermap.put("repeat_check", repeat_check);
//        }
        headermap.put("ucg_flag", "y");
        String mediaType = "application/json;charset=utf-8";


        // 根据安全级别选择加密或压缩请求表体参数
        String json = dealRequestBody(requestBody, security_key, secret_level);

        // 返回值
        String postResult = doPost(url, null, mediaType, headermap, json);

        return dealResponseBody(postResult, security_key, secret_level);
    }

    /**
     * 获取access_token
     *
     * @return
     * @throws Exception
     */
    private static String getToken() throws Exception {
        String token = null;
        if ("password".equals(grant_type)) {
            // 密码模式
            token = getTokenByPWD();
        } else if ("client_credentials".equals(grant_type)) {
            // 客户端模式
            token = getTokenByClient();
        }
        return token;
    }



    /**
     * 客户端模式获取token
     *
     * @return
     * @throws Exception
     */
    private static String getTokenByClient() throws Exception {
        Map<String, String> paramMap = new HashMap<>();
        // 密码模式认证
        paramMap.put("grant_type", "client_credentials");
        // 第三方应用id
        paramMap.put("client_id", client_id);
        // 第三方应用secret 公钥加密
        paramMap.put("client_secret", URLEncoder.encode(Encryption.pubEncrypt(pubKey, client_secret), "utf-8"));
        // 账套编码
        paramMap.put("biz_center", busi_center);

        // 签名
        String sign = SHA256Util.getSHA256(client_id + client_secret + pubKey,pubKey);

        paramMap.put("signature", sign);

        String url = baseUrl + "/nccloud/opm/accesstoken";
        String mediaType = "application/x-www-form-urlencoded";
        String token = doPost(url, paramMap, mediaType, null, "");
        return token;
    }

    /**
     * 密码模式获取token
     *
     * @return
     * @throws Exception
     */
    @SuppressWarnings("unused")
    private static  String getTokenByPWD() throws Exception {
        Map<String, String> paramMap = new HashMap<String, String>();
        // 密码模式认证
        paramMap.put("grant_type", "password");
        // 第三方应用id
        paramMap.put("client_id", client_id);
        // 第三方应用secret 公钥加密
        paramMap.put("client_secret", URLEncoder.encode(Encryption.pubEncrypt(pubKey, client_secret), "utf-8"));
//		paramMap.put("client_secret", client_secret);
        // ncc用户名
        paramMap.put("username", username);
        // 密码 公钥加密
        paramMap.put("password", URLEncoder.encode(Encryption.pubEncrypt(pubKey, pwd), "utf-8"));
//		paramMap.put("password", pwd);
        // 账套编码
        paramMap.put("biz_center", busi_center);
        // 签名
        String sign = SHA256Util.getSHA256(client_id + client_secret + username + pwd + pubKey, pubKey);
        System.out.println("sign_getToken::" + sign);
        paramMap.put("signature", sign);

        String url = baseUrl + "/nccloud/opm/accesstoken";
        String mediaType = "application/x-www-form-urlencoded";
        String token = doPost(url, paramMap, mediaType, null, "");
        return token;
    }


    /**
     * 根据安全级别设置，表体是否加密或压缩
     *
     * @param source
     * @param security_key
     * @param level
     * @return
     * @throws Exception
     */
    private static String dealRequestBody(String source, String security_key, String level) throws Exception {
        String result = null;
        if (StringUtils.isEmpty(level) || SecretConst.LEVEL0.equals(level)) {
            result = source;
        } else if (SecretConst.LEVEL1.equals(level)) {
            result = Encryption.symEncrypt(security_key, source);
        } else if (SecretConst.LEVEL2.equals(level)) {
            result = CompressUtil.gzipCompress(source);
        } else if (SecretConst.LEVEL3.equals(level)) {
            result = Encryption.symEncrypt(security_key, CompressUtil.gzipCompress(source));
        } else if (SecretConst.LEVEL4.equals(level)) {
            result = CompressUtil.gzipCompress(Encryption.symEncrypt(security_key, source));
        } else {
            throw new Exception("无效的安全等级");
        }

        return result;
    }

    /**
     * 返回值进行过加密和压缩，对返回值进行解压和解密
     *
     * @param source
     * @param security_key
     * @param level
     * @return
     * @throws Exception
     */
    private static String dealResponseBody(String source, String security_key, String level) throws Exception {
        String result = null;

        if (StringUtils.isEmpty(level) || SecretConst.LEVEL0.equals(level)) {
            result = source;
        } else if (SecretConst.LEVEL1.equals(level)) {
            result = Decryption.symDecrypt(security_key, source);
        } else if (SecretConst.LEVEL2.equals(level)) {
            result = CompressUtil.gzipDecompress(source);
        } else if (SecretConst.LEVEL3.equals(level)) {
            result = CompressUtil.gzipDecompress(Decryption.symDecrypt(security_key, source));
        } else if (SecretConst.LEVEL4.equals(level)) {
            result = Decryption.symDecrypt(security_key, CompressUtil.gzipDecompress(source));
        } else {
            throw new Exception("无效的安全等级");
        }

        return result;
    }

    /**
     * 发送post请求
     *
     * @param baseUrl
     * @param paramMap
     * @param mediaType
     * @param headers
     * @param json
     * @return
     */
    private static String doPost(String baseUrl, Map<String, String> paramMap, String mediaType, Map<String, String> headers, String json) {

        HttpURLConnection urlConnection = null;
        InputStream in = null;
        OutputStream out = null;
        BufferedReader bufferedReader = null;
        String result = null;
        try {
            StringBuffer sb = new StringBuffer();
            sb.append(baseUrl);
            if (paramMap != null) {
                sb.append("?");
                for (Map.Entry<String, String> entry : paramMap.entrySet()) {
                    String key = entry.getKey();
                    String value = entry.getValue();
                    sb.append(key + "=" + value).append("&");
                }
                baseUrl = sb.toString().substring(0, sb.toString().length() - 1);
            }

            URL urlObj = new URL(baseUrl);
            urlConnection = (HttpURLConnection) urlObj.openConnection();
            urlConnection.setConnectTimeout(50000);
            urlConnection.setRequestMethod("POST");
            urlConnection.setDoOutput(true);
            urlConnection.setDoInput(true);
            urlConnection.setUseCaches(false);
            urlConnection.addRequestProperty("content-type", mediaType);
            if (headers != null) {
                for (String key : headers.keySet()) {
                    urlConnection.addRequestProperty(key, headers.get(key));
                }
            }
            out = urlConnection.getOutputStream();
            out.write(json.getBytes("utf-8"));
            out.flush();
            int resCode = urlConnection.getResponseCode();
            if (resCode == HttpURLConnection.HTTP_OK || resCode == HttpURLConnection.HTTP_CREATED || resCode == HttpURLConnection.HTTP_ACCEPTED) {
                in = urlConnection.getInputStream();
            } else {
                in = urlConnection.getErrorStream();
            }
            bufferedReader = new BufferedReader(new InputStreamReader(in, "utf-8"));
            StringBuffer temp = new StringBuffer();
            String line = bufferedReader.readLine();
            while (line != null) {
                temp.append(line).append("\r\n");
                line = bufferedReader.readLine();
            }
            String ecod = urlConnection.getContentEncoding();
            if (ecod == null) {
                ecod = Charset.forName("utf-8").name();
            }
            result = new String(temp.toString().getBytes("utf-8"), ecod);
        } catch (Exception e) {
            System.out.println(e);
        } finally {
            if (null != bufferedReader) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != out) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != in) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            urlConnection.disconnect();
        }
        return result;
    }

    class SecretConst {
        /**
         * LEVEL0 不压缩、不加密
         */
        public static final String LEVEL0 = "L0";
        /**
         * LEVEL1 只加密、不压缩
         */
        public static final String LEVEL1 = "L1";
        /**
         * LEVEL2 只压缩、不加密
         */
        public static final String LEVEL2 = "L2";
        /**
         * LEVEL3 先压缩、后加密
         */
        public static final String LEVEL3 = "L3";
        /**
         * LEVEL4 先加密、后压缩
         */
        public static final String LEVEL4 = "L4";
    }
}
